#include "engine.h"

Engine::Engine(){
    quit=false;
    SDL_Surface* glSurface;

    SDL_Init( SDL_INIT_EVERYTHING );
    SDL_WM_SetCaption( "Increscent Porphyroid Disjuncture v0.0.8", NULL );
    SDL_ShowCursor(SDL_DISABLE);
    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
    if ( (glSurface = SDL_SetVideoMode( WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_BPP,  SDL_OPENGL)) == NULL){
		std::cout << "screen failed to load\n";
		quit=true;
    }
    swScreen = SDL_CreateRGBSurface(SDL_SWSURFACE,WINDOW_WIDTH,WINDOW_HEIGHT,WINDOW_BPP,
    								glSurface->format->Rmask , glSurface->format->Gmask, glSurface->format->Bmask, glSurface->format->Amask);

    SDL_FreeSurface(glSurface);

    init_GL();

    soundBoard = new SoundBoard();
    player = new Player(soundBoard);
    stage = new Stage();
    player->load_path();
    player->spawn();
    stage->newMap(player->get_map_filename());
    player->load_sprite();
    Uint8 *SDL_GetKeyState(int *numkeys);
    std::cout << "engine initilized\n";
}

/**
 * Initilize all our openGL fun stuffs.
 */
void Engine::init_GL(){
	glEnable( GL_TEXTURE_2D );

	glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );

	glViewport( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );

	glClear( GL_COLOR_BUFFER_BIT );

	glMatrixMode( GL_PROJECTION );
	glLoadIdentity();

	glOrtho(0.f, SCREEN_WIDTH, 0.f, SCREEN_HEIGHT, -1.0f, 1.0f);

	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity();

	// get the number of channels in the SDL screen
	nOfColors = swScreen->format->BytesPerPixel;
	if (nOfColors == 4)     // contains an alpha channel
	{
			if (swScreen->format->Rmask == 0x000000ff)
					texture_format = GL_RGBA;
			else
					texture_format = GL_BGRA;
	} else if (nOfColors == 3)     // no alpha channel
	{
			if (swScreen->format->Rmask == 0x000000ff)
					texture_format = GL_RGB;
			else
					texture_format = GL_BGR;
	} else {
			printf("warning: the screen is not truecolor..  this will probably break\n");
			// this error should not go unhandled
	}

	// Have OpenGL generate a texture object handle for us
	glGenTextures( 1, &screenTexture );

	// Bind the texture object
	glBindTexture( GL_TEXTURE_2D, screenTexture );

	// Set the texture's stretching properties
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
	//end openGL initilization
}

Engine::~Engine(){
	if(swScreen!=NULL)
		SDL_FreeSurface(swScreen);
    if(screenTexture)
    	glDeleteTextures( 1, &screenTexture );
    SDL_Quit();
}

bool Engine::flip(){
	//Update screen
    SDL_GL_SwapBuffers();
    return true;
}

bool Engine::running(){
    if(!quit)
    	return true;
    return false;
}

void Engine::framerate_limit(){
	int timeSpent = SDL_GetTicks() - lastTime;
    if( timeSpent < 1000 / FRAMES_PER_SECOND )
        SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - timeSpent);
}

void Engine::check_events(){
         while( SDL_PollEvent( &event ) ){
            if( event.type == SDL_QUIT ){
                quit=true;
                return;
            }
            gather_input();
        }
        Uint8 *keystate = SDL_GetKeyState(NULL);
        if(keystate[SDLK_LEFT] && !keystate[SDLK_RIGHT]){
			player->set_user_x_move(-5);
			player->nextFrame();
        }
        else if(keystate[SDLK_RIGHT] && !keystate[SDLK_LEFT]){
			player->set_user_x_move(5);
			player->nextFrame();
        }
        else{
        	player->setFrame(2);
        	player->set_user_x_move(0);
        }

}

void Engine::get_time(){
    lastTime = SDL_GetTicks();
}

void Engine::gather_input(){
    Uint8 *keystate = SDL_GetKeyState(NULL);
    if( event.type == SDL_KEYDOWN )
    {
        switch(event.key.keysym.sym){
            case SDLK_w:
            	stage->set_rot(180.0f); player->gravitySound();
            	break;
            case SDLK_a:
				stage->set_rot(270.0f); player->gravitySound();
				break;
            case SDLK_s:
				stage->set_rot(0.0f); player->gravitySound();
				break;
            case SDLK_d:
            	stage->set_rot(90.0f); player->gravitySound();
            	break;
            /*case SDLK_RETURN: if(keystate[SDLK_RALT] || keystate[SDLK_LALT]){if(hwScreen->flags & SDL_FULLSCREEN){hwScreen= SDL_SetVideoMode(WN); }else{hwScreen= SDL_SetVideoMode(FS);}}break;
            case SDLK_RALT: if(keystate[SDLK_RETURN]){if(hwScreen->flags & SDL_FULLSCREEN){hwScreen= SDL_SetVideoMode(WN); }else{hwScreen= SDL_SetVideoMode(FS);}}break;
            case SDLK_LALT: if(keystate[SDLK_RETURN]){if(hwScreen->flags & SDL_FULLSCREEN){hwScreen= SDL_SetVideoMode(WN); }else{hwScreen= SDL_SetVideoMode(FS);}}break;*/
            case SDLK_z: player->jump(stage);break;
            case SDLK_x: std::cout << "you are trying to dash";
            			if(keystate[SDLK_LEFT] && !keystate[SDLK_RIGHT] && !keystate[SDLK_UP] && !keystate[SDLK_DOWN])
                            player->dash(LEFT);
						if(!keystate[SDLK_LEFT] && keystate[SDLK_RIGHT] && !keystate[SDLK_UP] && !keystate[SDLK_DOWN])
							player->dash(RIGHT);
						if(!keystate[SDLK_LEFT] && !keystate[SDLK_RIGHT] && keystate[SDLK_UP] && !keystate[SDLK_DOWN])
							player->dash(UP);
						if(!keystate[SDLK_LEFT] && !keystate[SDLK_RIGHT] && !keystate[SDLK_UP] && keystate[SDLK_DOWN])
							player->dash(DOWN);
						break;
			case SDLK_LEFT: player->set_faceing_left(true);
				 break;
			case SDLK_RIGHT: player->set_faceing_left(false);
			 	 break;
        default: break;
        }
    }else if(event.type == SDL_KEYUP){
        switch(event.key.keysym.sym){
            case SDLK_LEFT: if(keystate[SDLK_RIGHT]){player->set_faceing_left(false);}break;
            case SDLK_RIGHT: if(keystate[SDLK_LEFT]){player->set_faceing_left(true);}break;
            default: break;
        }
    }



}
void Engine::update_objects(){
    player->move_player(stage);
}
void Engine::display(){
  stage->center_camera(player->get_x(), player->get_y(), player->get_w(), player->get_h());
  stage->display_terrain(swScreen);
  player->display_player(swScreen, stage->get_camera_x(), stage->get_camera_y());
  player->manage_particle_systems();
  player->display_all_particles(swScreen, stage->get_camera_x(), stage->get_camera_y(), stage->get_mapWidthpx(), stage->get_mapHeightpx());
  if(stage->is_done(player->get_x(), player->get_y())){
    player->nextMap();
    std::cout<<"newMap(" << player->get_map_filename() << ")\n";
    stage->newMap(player->get_map_filename());
    player->spawn();
    player->save_profile();
  }
  displayToGL();
}

/**
 * render our SDL_Surface onto a openGL quad to display to the screen.
 */
void Engine::displayToGL(){
	glClear(GL_COLOR_BUFFER_BIT);

	// Bind the texture object
	glBindTexture( GL_TEXTURE_2D, screenTexture );

	// Edit the texture object's image data using the information SDL_screen gives us
	glTexImage2D( GL_TEXTURE_2D, 0, nOfColors, swScreen->w, swScreen->h, 0,
					  texture_format, GL_UNSIGNED_BYTE, swScreen->pixels );

	glMatrixMode( GL_MODELVIEW );
	glPushMatrix();
		glLoadIdentity();
		glTranslatef(WINDOW_WIDTH/2, WINDOW_HEIGHT/2, 0.f);
		glRotatef(stage->get_rot() , 0.0f, 0.0f, 1.0f);
		glTranslatef(-WINDOW_WIDTH/2, -WINDOW_HEIGHT/2, 0.f);
		glBegin( GL_QUADS );
			//Bottom-left vertex (corner)
			glTexCoord2i( 0, 0 );
			glVertex3f( 0.f, WINDOW_HEIGHT, 0.f);

			//Bottom-right vertex (corner)
			glTexCoord2i( 1, 0 );
			glVertex3f( WINDOW_WIDTH, WINDOW_HEIGHT, 0.f);

			//Top-right vertex (corner)
			glTexCoord2i( 1, 1 );
			glVertex3f( WINDOW_WIDTH, 0, 0.f);

			//Top-left vertex (corner)
			glTexCoord2i( 0, 1 );
			glVertex3f( 0, 0, 0.f);
		glEnd();
	glPopMatrix();
}

